﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using HML.Design;

namespace HML
{
    /// <summary>
    /// 命令组按钮控件
    /// </summary>
    [Description("命令组按钮控件")]
    [DefaultProperty("Commands")]
    [DefaultEvent("Selected")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [Designer(typeof(CommandButtonDesigner))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(CommandButton), "Controls.CommandButton.Resources.CommandButton.bmp")]
    public class CommandButton : MainThreadAnimationControl, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(CommandButton)).GetName().Name, typeof(CommandButton).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled = SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);
            this.Invalidate();
        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            this.InitializeElement();
            this.Invalidate();
        }

        void ISkinObject.Invalidate()
        {
            this.Invalidate();
        }

        #endregion

        #region 新增事件

        public delegate void SelectingEventHandler(object sender, CommandButtonSelectingEventArgs e);
        private static readonly object EventSelecting = new object();
        /// <summary>
        /// 选中命令更改中事件
        /// </summary>
        [Description("选中命令更改中事件")]
        [Category("杂项")]
        public event SelectingEventHandler Selecting
        {
            add { Events.AddHandler(EventSelecting, value); }
            remove { Events.RemoveHandler(EventSelecting, value); }
        }

        private static readonly object EventSelected = new object();
        /// <summary>
        /// 选中命令更改后事件
        /// </summary>
        [Description("选中命令更改后事件")]
        [Category("杂项")]
        public event EventHandler Selected
        {
            add { Events.AddHandler(EventSelected, value); }
            remove { Events.RemoveHandler(EventSelected, value); }
        }

        #endregion

        #region 停用事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler PaddingChanged
        {
            add { base.PaddingChanged += value; }
            remove { base.PaddingChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler RightToLeftChanged
        {
            add { base.RightToLeftChanged += value; }
            remove { base.RightToLeftChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged
        {
            add { base.ImeModeChanged += value; }
            remove { base.ImeModeChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackColorChanged
        {
            add { base.BackColorChanged += value; }
            remove { base.BackColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TextChanged
        {
            add { base.TextChanged += value; }
            remove { base.TextChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ForeColorChanged
        {
            add { base.ForeColorChanged += value; }
            remove { base.ForeColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageChanged
        {
            add { base.BackgroundImageChanged += value; }
            remove { base.BackgroundImageChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageLayoutChanged
        {
            add { base.BackgroundImageLayoutChanged += value; }
            remove { base.BackgroundImageLayoutChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick
        {
            add { base.DoubleClick += value; }
            remove { base.DoubleClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseDoubleClick
        {
            add { base.MouseDoubleClick += value; }
            remove { base.MouseDoubleClick -= value; }
        }

        #endregion

        #region 新增属性

        private bool roundEnabled = true;
        /// <summary>
        /// 是否启用圆角
        /// </summary>
        [Description("是否启用圆角")]
        [Category("杂项")]
        [PropertyOrder(-196)]
        [DefaultValue(true)]
        public bool RoundEnabled
        {
            get { return this.roundEnabled; }
            set
            {
                if (this.roundEnabled == value)
                    return;

                this.roundEnabled = value;
                this.SetControlShape();
                this.Invalidate();
            }
        }

        private bool autoWidth = false;
        /// <summary>
        /// 命令自动宽度模式
        /// </summary>
        [Description("命令自动宽度模式")]
        [Category("杂项")]
        [PropertyOrder(-188)]
        [DefaultValue(false)]
        public bool AutoWidth
        {
            get { return this.autoWidth; }
            set
            {
                if (this.autoWidth == value)
                    return;

                this.autoWidth = value;
                this.InitializeElement();
                this.Invalidate();
            }
        }

        private int autoWidthMin = 70;
        /// <summary>
        /// 命令最小宽度(自动宽度模式下)
        /// </summary>
        [Description("命令最小宽度(自动宽度模式下)")]
        [Category("杂项")]
        [PropertyOrder(-186)]
        [DefaultValue(70)]
        public int AutoWidthMin
        {
            get { return this.autoWidthMin; }
            set
            {
                if (this.autoWidthMin == value || value <= 0)
                    return;

                this.autoWidthMin = value;
                this.InitializeElement();
                this.Invalidate();
            }
        }

        private int fixedWidth = 70;
        /// <summary>
        /// 命令固定宽度
        /// </summary>
        [Description("命令固定宽度")]
        [Category("杂项")]
        [PropertyOrder(-184)]
        [DefaultValue(70)]
        public int FixedWidth
        {
            get { return this.fixedWidth; }
            set
            {
                if (this.fixedWidth == value)
                    return;

                this.fixedWidth = value;
                this.InitializeElement();
                this.Invalidate();
            }
        }

        private Padding textMargin = new Padding(3, 3, 3, 3);
        /// <summary>
        /// 命令文本外边距
        /// </summary>
        [Description("命令文本外边距")]
        [Category("杂项")]
        [PropertyOrder(-182)]
        [DefaultValue(typeof(Padding), "3, 3, 3, 3")]
        public Padding TextMargin
        {
            get { return this.textMargin; }
            set
            {
                if (value.Left < 0)
                    value.Left = 0;
                if (value.Right < 0)
                    value.Right = 0;
                if (value.Top < 0)
                    value.Top = 0;
                if (value.Bottom < 0)
                    value.Bottom = 0;
                if (this.textMargin == value)
                    return;

                this.textMargin = value;
                this.InitializeElement();
                this.Invalidate();
            }
        }

        private CommandButtonTextAlignment textAlignment = CommandButtonTextAlignment.Center;
        /// <summary>
        /// 命令文本对齐方式
        /// </summary>
        [Description("命令文本对齐方式")]
        [Category("杂项")]
        [PropertyOrder(-180)]
        [DefaultValue(CommandButtonTextAlignment.Center)]
        public CommandButtonTextAlignment TextAlignment
        {
            get { return this.textAlignment; }
            set
            {
                if (this.textAlignment == value)
                    return;

                this.textAlignment = value;
                this.Invalidate();
            }
        }

        private bool deSelectEnabled = false;
        /// <summary>
        /// 是否允许鼠标键盘取消当前选中的命令
        /// </summary>
        [Description("是否允许鼠标键盘取消当前选中的命令")]
        [Category("杂项")]
        [PropertyOrder(-174)]
        [DefaultValue(false)]
        public bool DeSelectEnabled
        {
            get { return this.deSelectEnabled; }
            set
            {
                if (this.deSelectEnabled == value)
                    return;

                this.deSelectEnabled = value;
            }
        }

        private CommandButtonCommandCollection commandsCollection;
        /// <summary>
        /// 命令集合
        /// </summary>
        [Description("命令集合")]
        [Category("杂项")]
        [PropertyOrder(-172)]
        [DefaultValue(null)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public CommandButtonCommandCollection Commands
        {
            get
            {
                if (this.commandsCollection == null)
                    this.commandsCollection = new CommandButtonCommandCollection(this);
                return this.commandsCollection;
            }
        }

        private CommandButtonCommand selectedCommand = null;
        /// <summary>
        /// 已选中命令
        /// </summary>
        [Browsable(false)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public CommandButtonCommand SelectedCommand
        {
            get { return this.selectedCommand; }
            set
            {
                if (value != null && !this.Commands.Contains(value))
                {
                    value = null;
                }
                if (this.selectedCommand == value)
                    return;

                CommandButtonSelectingEventArgs arg = new CommandButtonSelectingEventArgs(this.selectedCommand, value);
                this.OnSelecting(arg);
                if (arg.Cancel)
                {
                    return;
                }

                this.selectedCommand = value;
                this.OnSelected(EventArgs.Empty);

                this.Invalidate();
            }
        }

        #endregion

        #region 重写属性

        public override Font Font
        {
            get { return base.Font; }
            set
            {
                base.Font = value;

                this.InitializeElement();
                this.Invalidate();
            }

        }

        protected override ImeMode DefaultImeMode
        {
            get { return ImeMode.Disable; }
        }

        #endregion

        #region 停用属性

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode
        {
            get { return base.ImeMode; }
            set { base.ImeMode = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override RightToLeft RightToLeft
        {
            get { return base.RightToLeft; }
            set { base.RightToLeft = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImageLayout BackgroundImageLayout
        {
            get { return base.BackgroundImageLayout; }
            set { base.BackgroundImageLayout = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Color BackColor
        {
            get { return this.StyleAppearance.UnSelected.Normal.BackColor; }
            set { }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color ForeColor
        {
            get { return this.StyleAppearance.UnSelected.Normal.TextColor; }
            set { }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 控件激活显示状态（配合Focused 、ShowFocusCues、activatedIndex使用）
        /// </summary>
        private bool activatedState = false;
        /// <summary>
        /// 控件激活状态选项索引
        /// </summary>
        private int activatedIndex = -1;

        /// <summary>
        /// 当前鼠标已按下的对象
        /// </summary>
        private object mousedownobject = null;
        /// <summary>
        /// 当前鼠标已进入的对象
        /// </summary>
        private object mouseenterobject = null;

        /// <summary>
        /// 动画rect
        /// </summary>
        private Rectangle animationrect = Rectangle.Empty;
        /// <summary>
        /// 动画坐标
        /// </summary>
        private Point animationpoint = Point.Empty;
        /// <summary>
        /// 动画总时间
        /// </summary>
        private double allAnimationTimeTime = 250;
        /// <summary>
        /// 动画已使用的时间
        /// </summary>
        private double usedAnimationTimeTime = 0;

        /// <summary>
        /// 边框
        /// </summary>
        private int borderThicknes = 1;

        #endregion

        public CommandButton()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.StandardClick, true);
            SetStyle(ControlStyles.StandardDoubleClick, false);

            this.SetControlShape();
            this.OnSkinChanged();
        }

        #region 重写

        protected override void OnScaleDpiChangedInitialize()
        {
            this.InitializeElement();
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;

            Padding scale_itemTextMargin = new Padding((int)Math.Ceiling(this.TextMargin.Left * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Top * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Right * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Bottom * this.ScaleDpi));

            Color border_color = this.Enabled ? this.StyleAppearance.UnSelected.Normal.BorderColor : this.StyleAppearance.UnSelected.Disabled.BorderColor;

            //选项
            SolidBrush back_sb = new SolidBrush(Color.White);
            SolidBrush text_sb = new SolidBrush(Color.White);
            for (int i = 0; i < this.Commands.Count; i++)
            {
                if (!this.Commands[i].Visible)
                    continue;

                CommandButtonCommand item = this.Commands[i];
                StyleAppearanceObject.StateAppearanceObject stateAppearance = (this.SelectedCommand == item) ? this.StyleAppearance.Selected : this.StyleAppearance.UnSelected;
                if (!this.Enabled || !item.Enabled)
                {
                    back_sb.Color = stateAppearance.Disabled.BackColor;
                    text_sb.Color = stateAppearance.Disabled.TextColor;
                }
                else if (this.Commands[i].IsMouseEnter)
                {
                    back_sb.Color = stateAppearance.Enter.BackColor;
                    text_sb.Color = stateAppearance.Enter.TextColor;
                }
                else
                {
                    back_sb.Color = stateAppearance.Normal.BackColor;
                    text_sb.Color = stateAppearance.Normal.TextColor;
                }

                //背景
                g.FillRectangle(back_sb, item.Rect);

                //点击动画
                if (this.animationrect != Rectangle.Empty)
                {
                    g.SmoothingMode = SmoothingMode.AntiAlias;
                    g.SetClip(this.animationrect);
                    int animationRadius = (int)Math.Ceiling(ControlHelper.AdjustRectangleMaxRadiusForPoint(this.animationrect, this.animationpoint) * this.usedAnimationTimeTime / this.allAnimationTimeTime * 10 / 8);
                    back_sb.Color = ControlHelper.ConvertToAnimationColor(back_sb.Color);
                    g.FillEllipse(back_sb, new RectangleF(this.animationpoint.X - animationRadius, this.animationpoint.Y - animationRadius, animationRadius * 2, animationRadius * 2));
                    g.ResetClip();
                    g.SmoothingMode = SmoothingMode.Default;
                }

                // 文本
                if (!String.IsNullOrEmpty(item.Text))
                {
                    g.DrawString(item.Text, this.Font, text_sb, item.Text_Rect.Location, StringFormat.GenericTypographic);
                }
            }

            //选项分隔线
            if (this.Commands.Count > 1)
            {
                g.SmoothingMode = SmoothingMode.Default;
                Pen splitter_pen = new Pen(border_color);
                for (int i = 0; i < this.Commands.Count - 1; i++)
                {
                    CommandButtonCommand item = this.Commands[i];
                    g.DrawLine(splitter_pen, new Point(item.Rect.Right, item.Rect.Y + this.borderThicknes), new Point(item.Rect.Right, item.Rect.Bottom - this.borderThicknes));
                }
                splitter_pen.Dispose();
            }

            //边框
            ControlHelper.DrawControlBorder(this, g, this.RoundEnabled, border_color, this.BackColor, back_sb.Color);

            back_sb.Dispose();
            text_sb.Dispose();

            //控件激活状态虚线框
            if (this.Focused && (this.ShowFocusCues || this.activatedState))
            {
                if (this.activatedIndex > -1 && this.activatedIndex < this.Commands.Count && this.Commands[this.activatedIndex].Visible && this.Commands[this.activatedIndex].Enabled)
                {
                    CommandButtonCommand item = this.Commands[this.activatedIndex];
                    Rectangle activated_border_rect = new Rectangle(item.Rect.X + 3, item.Rect.Y + 3, item.Rect.Width - 7, item.Rect.Height - 7);
                    Pen activated_border_pen = new Pen(this.StyleAppearance.ActivateColor) { DashStyle = DashStyle.Dot };
                    g.DrawRectangle(activated_border_pen, activated_border_rect);
                    activated_border_pen.Dispose();
                }
            }

        }

        protected override void Select(bool directed, bool forward)
        {
            if (GetActivatedIndexList().Count > 0)
            {
                base.Select(directed, forward);

                this.activatedState = true;
                this.activatedIndex = 0;
                this.Invalidate();
            }
            else
            {
                IContainerControl c = this.Parent.GetContainerControl();
                if (c != null)
                {
                    ((Control)c).SelectNextControl(this, true, true, true, true);
                }
            }
        }

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);

            this.activatedIndex = 0;
            this.Invalidate();
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);

            this.mousedownobject = null;
            this.mouseenterobject = null;
            this.activatedState = false;
            this.Invalidate();
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);

            this.mousedownobject = null;
            this.mouseenterobject = null;
            this.Invalidate();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (!this.Focused)
            {
                this.Focus();
            }

            if (e.Button == MouseButtons.Left)
            {
                for (int i = 0; i < this.Commands.Count; i++)
                {
                    CommandButtonCommand command = this.Commands[i];
                    if (command.Visible && command.Rect.Contains(e.Location))
                    {
                        if (this.Commands[i].Enabled)
                        {
                            this.mousedownobject = command;
                            this.activatedIndex = i;
                            this.Invalidate();
                        }
                        break;
                    }
                }
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                if (this.mousedownobject != null)
                {
                    CommandButtonCommand command = (CommandButtonCommand)this.mousedownobject;
                    if (command.Visible && command.Rect.Contains(e.Location))
                    {
                        if (command.Enabled)
                        {
                            this.usedAnimationTimeTime = 0;
                            this.animationpoint = e.Location;
                            this.animationrect = command.Rect;
                            this.Invalidate();
                            MainThreadAnimationControl.AnimationStart(this);

                            this.UISelectCommand(command);
                        }
                    }
                }
            }
            this.mousedownobject = null;

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (this.mousedownobject == null)
            {
                CommandButtonCommand command_tmp = null;
                for (int i = 0; i < this.Commands.Count; i++)
                {
                    CommandButtonCommand command = this.Commands[i];
                    if (command.Visible && command.Rect.Contains(e.Location))
                    {
                        if (command.Enabled)
                        {
                            command_tmp = command;
                        }
                        break;
                    }
                }
                if (this.mouseenterobject != command_tmp)
                {
                    this.mouseenterobject = command_tmp;
                    this.Invalidate();
                }
            }
        }

        protected override bool ProcessDialogKey(Keys keyData)
        {
            switch (keyData)
            {
                case Keys.Left:
                    {
                        this.activatedState = true;

                        List<int> indexArr = GetActivatedIndexList();
                        if (indexArr.Count > 0)
                        {
                            int indexArr_index = indexArr.IndexOf(this.activatedIndex);
                            if (indexArr_index == -1)
                            {
                                indexArr_index = 0;
                            }

                            indexArr_index--;
                            if (indexArr_index < 0)
                            {
                                indexArr_index = indexArr.Count - 1;
                            }
                            this.activatedIndex = indexArr[indexArr_index];
                            this.Invalidate();
                        }
                        return true;
                    }
                case Keys.Right:
                    {
                        this.activatedState = true;

                        List<int> indexArr = GetActivatedIndexList();
                        if (indexArr.Count > 0)
                        {
                            int indexArr_index = indexArr.IndexOf(this.activatedIndex);
                            if (indexArr_index == -1)
                            {
                                indexArr_index = 0;
                            }

                            indexArr_index++;
                            if (indexArr_index > indexArr.Count - 1)
                            {
                                indexArr_index = 0;
                            }
                            this.activatedIndex = indexArr[indexArr_index];
                            this.Invalidate();
                        }
                        return true;
                    }
                case Keys.Space:
                    {
                        if (this.activatedIndex > -1 && this.activatedIndex < this.Commands.Count && this.Commands[this.activatedIndex].Enabled)
                        {
                            CommandButtonCommand command = this.Commands[this.activatedIndex];

                            this.usedAnimationTimeTime = 0;
                            this.animationpoint = new Point(command.Rect.X + command.Rect.Width / 2, command.Rect.Y + command.Rect.Height / 2); ;
                            this.animationrect = command.Rect;
                            this.mousedownobject = command;
                            MainThreadAnimationControl.AnimationStart(this);
                            this.Invalidate();

                            this.UISelectCommand(command);
                        }
                        return true;
                    }
            }

            return base.ProcessDialogKey(keyData);
        }

        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            Size size = this.GetControlAutoSize();
            width = size.Width;
            height = size.Height;

            base.SetBoundsCore(x, y, width, height, specified);

            this.UpdateItemsRectangle();
            this.SetControlShape();
            this.Invalidate();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                MainThreadAnimationControl.AnimationStop(this);
            }
            base.Dispose(disposing);
        }

        /// <summary>
        /// 动画控件动画中要处理的内容(不能时耗时操作)
        /// </summary>
        /// <param name="interval">动画定时器间隔时间</param>
        protected override void Animationing(int interval)
        {
            bool finish = false;
            this.usedAnimationTimeTime += interval;
            if (this.usedAnimationTimeTime > this.allAnimationTimeTime)
            {
                this.usedAnimationTimeTime = this.allAnimationTimeTime;
                MainThreadAnimationControl.AnimationStop(this);
                finish = true;
            }

            if (finish)
            {
                this.usedAnimationTimeTime = 0;
                this.animationpoint = Point.Empty;
                this.animationrect = Rectangle.Empty;
            }

            this.Invalidate();
        }

        #endregion

        #region 虚方法

        protected virtual void OnSelecting(CommandButtonSelectingEventArgs e)
        {
            SelectingEventHandler handler = Events[EventSelecting] as SelectingEventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected virtual void OnSelected(EventArgs e)
        {
            EventHandler handler = Events[EventSelected] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region 公开方法

        /// <summary>
        /// 更新选中命令（不会触发 Selecting、Selected 事件）
        /// </summary>
        /// <param name="command">要选中命令</param>
        public void UpdateCommand(CommandButtonCommand command)
        {
            CommandButtonCommand command_tmp = command;
            if (command_tmp != null && !this.Commands.Contains(command_tmp))
            {
                command_tmp = null;
            }
            if (this.selectedCommand == command_tmp)
                return;

            this.selectedCommand = command_tmp;
            this.Invalidate();
        }

        /// <summary>
        /// 鼠标是否进入命令对象
        /// </summary>
        /// <param name="command">命令对象</param>
        /// <returns></returns>
        internal bool IsMouseEnter(CommandButtonCommand command)
        {
            return (command != null && this.mouseenterobject == command);
        }

        #endregion

        #region 公开方法

        /// <summary>
        /// 初始化控件内部元素布局
        /// </summary>
        public void InitializeElement()
        {
            this.UpdateItemsTextSize();
            this.SetBoundsCore(this.Location.X, this.Location.Y, this.Width, this.Height, BoundsSpecified.Size);
        }

        #endregion 

        #region 私有方法

        /// <summary>
        /// 更新选项文本Size
        /// </summary>
        private void UpdateItemsTextSize()
        {
            NativeMethods.TEXTMETRIC font_metrics = ControlHelper.GetFontMetrics(this.Handle, this.Font);

            IntPtr hDC = IntPtr.Zero;
            Graphics g = null;
            ControlHelper.GetWindowClientGraphics(this.Handle, out g, out hDC);

            for (int i = 0; i < this.Commands.Count; i++)
            {
                CommandButtonCommand item = this.Commands[i];
                item.Text_Size = !item.Visible ? new Size(0, font_metrics.GetFontRealHeight()) : new Size((int)Math.Ceiling(g.MeasureString(item.Text, this.Font, int.MaxValue, StringFormat.GenericTypographic).Width), font_metrics.GetFontRealHeight());
            }

            g.Dispose();
            NativeMethods.ReleaseDC(this.Handle, hDC);
        }

        /// <summary>
        /// 更新选项Rectangle
        /// </summary>
        private void UpdateItemsRectangle()
        {
            int scale_itemFixedWidth = (int)Math.Ceiling(this.FixedWidth * this.ScaleDpi);
            Padding scale_itemTextMargin = new Padding((int)Math.Ceiling(this.TextMargin.Left * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Top * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Right * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Bottom * this.ScaleDpi));

            for (int i = 0; i < this.Commands.Count; i++)
            {
                CommandButtonCommand item = this.Commands[i];
                int x = (i == 0 ? (this.ClientRectangle.X) : (this.Commands[i - 1].Rect.Right));
                int y = this.ClientRectangle.Y;
                int w = item.Visible == false ? 0 : (!this.AutoWidth ? scale_itemFixedWidth : Math.Max(this.AutoWidthMin, scale_itemTextMargin.Left + item.Text_Size.Width + scale_itemTextMargin.Right));
                int h = this.borderThicknes + scale_itemTextMargin.Top + this.Commands[i].Text_Size.Height + scale_itemTextMargin.Bottom + this.borderThicknes;
                item.Rect = new Rectangle(x, y, w, h);

                int text_x = (item.Rect.X + scale_itemTextMargin.Left);
                if (!this.AutoWidth)
                {
                    if (this.TextAlignment == CommandButtonTextAlignment.Left)
                    {
                        text_x = (item.Rect.X + scale_itemTextMargin.Left);
                    }
                    else if (this.TextAlignment == CommandButtonTextAlignment.Right)
                    {
                        text_x = (item.Rect.Right - scale_itemTextMargin.Right - item.Text_Size.Width);
                    }
                    else
                    {
                        text_x = (int)(item.Rect.X + (item.Rect.Width - item.Text_Size.Width) / 2f);
                    }
                }
                else
                {
                    if (this.TextAlignment == CommandButtonTextAlignment.Right)
                    {
                        text_x = (item.Rect.Right - scale_itemTextMargin.Right - item.Text_Size.Width);
                    }
                    else if (this.TextAlignment == CommandButtonTextAlignment.Center)
                    {
                        text_x = (int)(item.Rect.X + (item.Rect.Width - item.Text_Size.Width) / 2f);
                    }
                    if (text_x < (item.Rect.X + scale_itemTextMargin.Left))
                    {
                        text_x = (item.Rect.X + scale_itemTextMargin.Left);
                    }
                }
                item.Text_Rect = new Rectangle(text_x, item.Rect.Y + this.borderThicknes + scale_itemTextMargin.Top, item.Text_Size.Width, item.Text_Size.Height);
            }
        }

        /// <summary>
        /// 根据设置获取控件Size
        /// </summary>
        /// <returns></returns>
        private Size GetControlAutoSize()
        {
            NativeMethods.TEXTMETRIC font_metrics = ControlHelper.GetFontMetrics(this.Handle, this.Font);
            int scale_itemFixedWidth = (int)Math.Ceiling(this.FixedWidth * this.ScaleDpi);
            Padding scale_itemTextMargin = new Padding((int)Math.Ceiling(this.TextMargin.Left * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Top * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Right * this.ScaleDpi), (int)Math.Ceiling(this.TextMargin.Bottom * this.ScaleDpi));

            int control_width = 0;
            int control_height = this.borderThicknes + scale_itemTextMargin.Top + font_metrics.GetFontRealHeight() + scale_itemTextMargin.Bottom + this.borderThicknes;
            for (int i = 0; i < this.Commands.Count; i++)
            {
                CommandButtonCommand item = this.Commands[i];
                if (item.Visible)
                {
                    control_width += (!this.AutoWidth ? scale_itemFixedWidth : Math.Max(this.AutoWidthMin, scale_itemTextMargin.Left + item.Text_Size.Width + scale_itemTextMargin.Right));
                }
            }

            return new Size(control_width, control_height);
        }

        /// <summary>
        /// 设置控件形状
        /// </summary>
        private void SetControlShape()
        {
            if (this.RoundEnabled)
            {
                GraphicsPath gp = ControlHelper.AdjustRectangleShapePath(this.ClientRectangle);
                this.Region = new Region(gp);
                gp.Dispose();
            }
            else
            {
                this.Region = new Region(this.ClientRectangle);
            }
        }

        /// <summary>
        /// 鼠标键盘设置选中命令
        /// </summary>
        /// <param name="command">将要选中命令</param>
        private void UISelectCommand(CommandButtonCommand command)
        {
            CommandButtonCommand command_tmp = command;
            if (command_tmp != null && !this.Commands.Contains(command_tmp))
            {
                command_tmp = null;
            }
            if (command_tmp != null)
            {
                if (this.DeSelectEnabled)
                {
                    if (this.selectedCommand == command_tmp)
                    {
                        command_tmp = null;
                    }
                }
            }

            if (this.selectedCommand == command_tmp)
                return;

            CommandButtonSelectingEventArgs arg = new CommandButtonSelectingEventArgs(this.selectedCommand, command_tmp);
            this.OnSelecting(arg);
            if (arg.Cancel)
            {
                return;
            }

            this.selectedCommand = command_tmp;
            this.OnSelected(EventArgs.Empty);

            this.Invalidate();
        }

        /// <summary>
        /// 获取允许激活命令索引集合
        /// </summary>
        /// <returns></returns>
        private List<int> GetActivatedIndexList()
        {
            List<int> indexList = new List<int>();
            for (int i = 0; i < this.Commands.Count; i++)
            {
                if (this.Commands[i].Visible && this.Commands[i].Enabled)
                {
                    indexList.Add(i);
                }
            }

            return indexList;
        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinActivateColor = Color.Empty;
            private readonly Color defaultActivateColor = SystemColors.Window;
            private Color activateColor = Color.Empty;
            /// <summary>
            /// 控件激活的虚线框颜色
            /// </summary>
            [Description("控件激活的虚线框颜色")]
            [PropertyOrder(-200)]
            [SkinProperty(true, false)]
            public Color ActivateColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinActivateColor;
                    }

                    if (this.activateColor != Color.Empty)
                    {
                        return this.activateColor;
                    }

                    return this.defaultActivateColor;
                }
                set
                {
                    if (this.activateColor == value)
                        return;

                    this.activateColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeActivateColor()
            {
                return this.activateColor != Color.Empty;
            }
            private void ResetActivateColor()
            {
                this.activateColor = Color.Empty;
                this.Invalidate();
            }

            private StateAppearanceObject unSelected;
            /// <summary>
            /// 未选中状态外观
            /// </summary>
            [Description("未选中状态外观")]
            [PropertyOrder(-178)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public StateAppearanceObject UnSelected
            {
                get
                {
                    if (this.unSelected == null)
                        this.unSelected = new StateAppearanceObject(this.owner, this
                            , SystemColors.ActiveCaption
                            , SystemColors.GradientActiveCaption
                            , SystemColors.ButtonHighlight
                            , SystemColors.ActiveCaption
                            , SystemColors.ActiveCaption
                            , SystemColors.ButtonHighlight
                            , SystemColors.InactiveCaption
                            , SystemColors.InactiveCaption
                            , SystemColors.ButtonHighlight
                            );
                    return this.unSelected;
                }
            }

            private StateAppearanceObject selected;
            /// <summary>
            /// 已选中状态外观
            /// </summary>
            [Description("已选中状态外观")]
            [PropertyOrder(-176)]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
            [SkinProperty(true, false)]
            public StateAppearanceObject Selected
            {
                get
                {
                    if (this.selected == null)
                        this.selected = new StateAppearanceObject(this.owner, this
                            , SystemColors.ActiveCaption
                            , SystemColors.ActiveCaption
                            , SystemColors.ButtonHighlight
                            , SystemColors.ActiveCaption
                            , SystemColors.GradientActiveCaption
                            , SystemColors.ButtonHighlight
                            , SystemColors.InactiveCaption
                            , SystemColors.InactiveCaption
                            , SystemColors.ButtonHighlight
                            );
                    return this.selected;
                }
            }

            #endregion

            public class StateAppearanceObject : AppearanceObjectBase
            {
                internal StateAppearanceObject(ISkinObject owner, AppearanceObjectBase parent, Color borderNormalColor, Color backNormalColor, Color textNormalColor, Color borderEnterColor, Color backEnterColor, Color textEnterColor, Color borderDisabledColor, Color backDisabledColor, Color textDisabledColor) : base(owner, parent)
                {
                    this.borderNormalColor = borderNormalColor;
                    this.backNormalColor = backNormalColor;
                    this.textNormalColor = textNormalColor;
                    this.borderEnterColor = borderEnterColor;
                    this.backEnterColor = backEnterColor;
                    this.textEnterColor = textEnterColor;
                    this.borderDisabledColor = borderDisabledColor;
                    this.backDisabledColor = backDisabledColor;
                    this.textDisabledColor = textDisabledColor;
                }

                #region 属性

                private Color borderNormalColor = Color.Empty;
                private Color backNormalColor = Color.Empty;
                private Color textNormalColor = Color.Empty;
                private ItemAppearanceObject normal;
                /// <summary>
                /// 正常状态
                /// </summary>
                [Description("正常状态")]
                [PropertyOrder(-194)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
                [SkinProperty(true, false)]
                public ItemAppearanceObject Normal
                {
                    get
                    {
                        if (this.normal == null)
                            this.normal = new ItemAppearanceObject(this.owner, this, this.borderNormalColor, this.backNormalColor, this.textNormalColor);
                        return this.normal;
                    }
                }

                private Color borderEnterColor = Color.Empty;
                private Color backEnterColor = Color.Empty;
                private Color textEnterColor = Color.Empty;
                private ItemAppearanceObject enter;
                /// <summary>
                /// 鼠标进入状态
                /// </summary>
                [Description("鼠标进入状态")]
                [PropertyOrder(-192)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
                [SkinProperty(true, false)]
                public ItemAppearanceObject Enter
                {
                    get
                    {
                        if (this.enter == null)
                            this.enter = new ItemAppearanceObject(this.owner, this, this.borderEnterColor, this.backEnterColor, this.textEnterColor);
                        return this.enter;
                    }
                }

                private Color borderDisabledColor = Color.Empty;
                private Color backDisabledColor = Color.Empty;
                private Color textDisabledColor = Color.Empty;
                private ItemAppearanceObject disabled;
                /// <summary>
                /// 禁用状态
                /// </summary>
                [Description("禁用状态")]
                [PropertyOrder(-190)]
                [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
                [SkinProperty(true, false)]
                public ItemAppearanceObject Disabled
                {
                    get
                    {
                        if (this.disabled == null)
                            this.disabled = new ItemAppearanceObject(this.owner, this, this.borderDisabledColor, this.backDisabledColor, this.textDisabledColor);
                        return this.disabled;
                    }
                }

                #endregion

                public class ItemAppearanceObject : AppearanceObjectBase
                {
                    internal ItemAppearanceObject(ISkinObject owner, AppearanceObjectBase parent, Color borderColor, Color backColor, Color textColor) : base(owner, parent)
                    {
                        this.defaultBorderColor = borderColor;
                        this.defaultBackColor = backColor;
                        this.defaultTextColor = textColor;
                    }

                    #region 属性

                    private Color skinBorderColor = Color.Empty;
                    private readonly Color defaultBorderColor = Color.Empty;
                    private Color borderColor = Color.Empty;
                    /// <summary>
                    /// 边框颜色
                    /// </summary>
                    [Description("边框颜色")]
                    [PropertyOrder(-159)]
                    [SkinProperty(true, false)]
                    public Color BorderColor
                    {
                        get
                        {
                            if (this.owner.GetSkinObjectSkinStateCore())
                            {
                                return this.skinBorderColor;
                            }

                            if (this.borderColor != Color.Empty)
                            {
                                return this.borderColor;
                            }

                            return this.defaultBorderColor;
                        }
                        set
                        {
                            if (this.borderColor == value)
                                return;

                            this.borderColor = value;
                            this.Invalidate();
                        }
                    }
                    private bool ShouldSerializeBorderColor()
                    {
                        return this.borderColor != Color.Empty;
                    }
                    private void ResetBorderColor()
                    {
                        this.borderColor = Color.Empty;
                        this.Invalidate();
                    }

                    private Color skinBackColor = Color.Empty;
                    private readonly Color defaultBackColor = Color.Empty;
                    private Color backColor = Color.Empty;
                    /// <summary>
                    /// 背景颜色
                    /// </summary>
                    [Description("背景颜色")]
                    [PropertyOrder(-158)]
                    [SkinProperty(true, false)]
                    public Color BackColor
                    {
                        get
                        {
                            if (this.owner.GetSkinObjectSkinStateCore())
                            {
                                return this.skinBackColor;
                            }

                            if (this.backColor != Color.Empty)
                            {
                                return this.backColor;
                            }

                            return this.defaultBackColor;
                        }
                        set
                        {
                            if (this.backColor == value)
                                return;

                            this.backColor = value;
                            this.Invalidate();
                        }
                    }
                    private bool ShouldSerializeBackColor()
                    {
                        return this.backColor != Color.Empty;
                    }
                    private void ResetBackColor()
                    {
                        this.backColor = Color.Empty;
                        this.Invalidate();
                    }

                    private Color skinTextColor = Color.Empty;
                    private readonly Color defaultTextColor = Color.Empty;
                    private Color textColor = Color.Empty;
                    /// <summary>
                    /// 文本颜色
                    /// </summary>
                    [Description("文本颜色")]
                    [PropertyOrder(-157)]
                    [SkinProperty(true, false)]
                    public Color TextColor
                    {
                        get
                        {
                            if (this.owner.GetSkinObjectSkinStateCore())
                            {
                                return this.skinTextColor;
                            }

                            if (this.textColor != Color.Empty)
                            {
                                return this.textColor;
                            }

                            return this.defaultTextColor;
                        }
                        set
                        {
                            if (this.textColor == value)
                                return;

                            this.textColor = value;
                            this.Invalidate();
                        }
                    }
                    private bool ShouldSerializeTextColor()
                    {
                        return this.textColor != Color.Empty;
                    }
                    private void ResetTextColor()
                    {
                        this.textColor = Color.Empty;
                        this.Invalidate();
                    }

                    #endregion

                }

            }

        }

        #endregion

    }
}
